home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 201-225 / disk_223 / ifftosun / ifftosun.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  28KB  |  970 lines

  1.  
  2.  
  3. /* TITLE:        IFF to Sun Raster Bitmap File Format.  Version 1.31 
  4.                  
  5.                  by Richard Frost, © 1989.
  6.                  
  7.                  If this is program is to be used for personal financial gain 
  8.                  PLEASE inform the author FIRST!
  9.  
  10.                  Please keep my name in this program, this is FREEWARE !!!
  11.                  
  12.                  
  13.                  SOON TO BE SUBMITTED FOR INCLUSION ON THE FISH LIBRARY!!
  14.                  (I hope !!)
  15.  
  16.                  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  17.  
  18.                  WARNING:  DO NOT attempt any file conversions into 
  19.                            RAM DISK or any normal disk until you 
  20.                            are sure that the disk has the space
  21.                            to hold the converted images, else
  22.                            the program will crash (I couldn't be 
  23.                            bothered checking for this) and you will
  24.                            get a friendly visit from MR GURU!
  25.  
  26.                            HALFBRITE NOT SUPPORTED YET!!!!
  27.                            
  28.  
  29.                  NOTE:     640 X 400 images create files that are
  30.                            over 256K long! (USE 1 MEG RAM or nearly
  31.                            an empty disk!)
  32.  
  33.                            Expect even larger than this for PAL
  34.                            (typically at most, say 704 X 512 ) images.
  35.  
  36.                            HAM images come out OK, as the colour choice
  37.                            algorithm needs some tweaking!
  38.                                
  39.                            Expect to see even faster conversions and better
  40.                            colour choice in the next versions and maybe
  41.                            HALFBRITE mode.
  42.  
  43.                  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  44.  
  45.                
  46.    AUTHOR:       Richard Frost,
  47.                     Adelaide (The Grand Prix State)
  48.                     South Australia,
  49.                     Australia. (Yes that place DOWN-UNDER! NOT AUSTRIA!!!)
  50.  
  51.                  You can mail any messages to me (RICHARD FROST) on the
  52.                  'ADAM-LINK' BBS (Located in Adelaide, South Australia) 
  53.                  
  54.  
  55.                  Using the IFF routines 'Jiff.c' by
  56.                  Jim Kent.
  57.  
  58.    HISTORY:    
  59.                  -  Started Version 1.0 7th February 1989.
  60.                  -  Version 1.0 WORKED FIRST TIME WITH NON-HAM images!!!
  61.                  -  HAM implementation 23rd February 1989.
  62.                  -  Aspect ratio correction for INTERLACE added 5th March 1989
  63.                  -  HAM finished 5th March 1989
  64.                  -  HAM checked on SUN 3/60 & working 6th March 1989
  65.                  -  HAM colour choice algorith improved (not completed yet)
  66.  
  67.                   
  68.  
  69.    BUGS:         As with all programs their complexity hides all bugs!.
  70.  
  71.                  - Funny things happen to memory & Workbench when input files
  72.                    hack up, ie LOTS of RAM NOT reallocated, an error in the
  73.                    READ IFF routine???
  74.  
  75.  
  76.    THANKS:       I must thank my friend ROBERT WOZNIAK for the idea
  77.                  behind the extra 'map_to' field in the histogram entry,
  78.                  which involved mapping ALL colours ONCE before the second
  79.                  pass of the screen and thus using the histogram as a look-up
  80.                  table. ROBERT'S very simple (yet INCREDIBLY EFFICIENT) idea
  81.                  has improved the speed of my program incredibly. 
  82.                  Thanks Rob !! (You are famous too now!!)
  83.                  
  84.                  I must also thank ALEX WAKEFIELD for his patience in porting
  85.                  generated SUN rasterfiles over to the SUN 3/60, and then putting
  86.                  up with DISK QUOTA errors on his SUN account !!
  87.  
  88.                  Once the AMIGA images got onto ETHERNET, boy did they travel 
  89.                  to other SUNS quick !!
  90.                  
  91.                  The Electronics Arts people who decided that there 
  92.                  should be ONE, and ONLY ONE standard image format on the AMIGA,
  93.                  IFF !!!
  94.  
  95.                  
  96.  
  97.    INFORMATION:  
  98.  
  99.    I hope you find this program as useful as I did. I did it mainly because
  100.    a friend of mine at university had access to a colour Sun 3/60. If you are
  101.    not aquainted with this computer, here are some juicy specs :
  102.  
  103.  
  104.        Resolution:             1152 X 900    (NON INTERLACED)
  105.                                 
  106.        Colour Pallete:         16 million colours to choose from
  107.  
  108.        Number of bitplanes:    8    ( means 256 on screen colours)
  109.  
  110.  
  111.      This means that you can view AMIGA INTERLACED pictures in their 
  112.    NON-INTERLACED form on the Sun, plus you have a VERY high resolution
  113.    which gives some pictures a photographic-like quality, (ie. the IFF
  114.    picture .. 'Legends', 'Dusky Hopping Mouse', 'Tiger' etc. !!!).
  115.  
  116.    Yes, this version DOES handle HAM pics, so now all those great HAM pics
  117.    out there can be ported to SUN Workstations!!! 
  118.  
  119.    NOTE:  I went to some effort in optimising the colour choice algorithm
  120.           as some HAM pics have LOTS of distinct on-screen colours!
  121.  
  122.           The classic HAM pic of an attractive lady's face holding a
  123.           pencil near her mouth has over 1300 distinct colours, from
  124.           this I had to choose a GOOD 256 palette for the SUN. My first
  125.           attempt was reasonable but the picture still had some very 
  126.           obvious colour defects for a few pixels which needed improving.              
  127.           
  128.      
  129.                                          I love the idea of STANDARDISATION !
  130.  
  131.                                                              Richard Frost.
  132.                                                              Adelaide,
  133.                                                              South Australia.
  134. */
  135.   
  136.  
  137. /* NOTE:  Full description of raster format omitted this time, in case of
  138.           copyright infringements with Sun Microsystems Inc. */
  139.  
  140.  
  141. #include  <exec/types.h>
  142. #include  <exec/nodes.h>
  143. #include  <exec/libraries.h>
  144. #include  <graphics/gfx.h>
  145. #include  <graphics/rastport.h>
  146. #include  <graphics/text.h>
  147. #include  <intuition/intuition.h>
  148. #include  <stdio.h>
  149. #include  <fcntl.h>
  150. #include  "jiff.h"
  151.  
  152.  
  153.            /* Sun TYPE definitions for it's own BITMAP FORMAT... */
  154.            /* each line of the image is rounded to 16 bits */
  155.  
  156.  
  157. #define RAS_MAGIC  0x59a66a95    /* Don't ask me how they decided on this number! */
  158. #define RT_STANDARD  1           /* Each scanline saved in 68000 order */
  159. #define RMT_EQUAL_RGB  1         /* Means we are using the RGB colour table vectors */ 
  160. #define RMT_NONE 0
  161. #define RMT_RAW 8
  162.  
  163.  
  164.                              /* colour macros .. */
  165.  
  166.  
  167.  
  168.                 /* macro for working out the distance between 2 colours */
  169.  
  170.  
  171. #define colourval(r,g,b) ( ((int)(r) << 4) + (int)(g) + ((int)(b) >> 4))
  172.  
  173. #define col_dist(r,g,b,r2,g2,b2) ( ((r-r2)*(r-r2)) + \
  174.                                    ((g-g2)*(g-g2)) + \
  175.                                    ((b-b2)*(b-b2)) ) 
  176.  
  177.                 /* extract the SCALED R G B for the SUN */
  178.                 /* ie. TOP nibble contains the 4bit value */
  179.  
  180. #define RED(col)   ((unsigned char ) ((col & 0x0f00) >> 4))
  181. #define GREEN(col) ((unsigned char ) (col & 0x00f0) )
  182. #define BLUE(col)  ((unsigned char ) ((col & 0x000f) << 4))
  183.  
  184. int NumCols,    /* Number of distinct colours in the palette */
  185.     LaceFlag;    /* internal flag to indicate INTERLACE PICS to other routines */
  186.  
  187.  
  188.  
  189.  
  190.  
  191. struct rasterfile 
  192.    {
  193.     long ras_magic;       /* Sun's Magic Number to identify the UNIX file type */
  194.     long ras_width;       /* Width of the Raster to be displayed */
  195.     long ras_height;      /* Height of the Raster to be displayed */
  196.     long ras_depth;       /* Number of bitplanes: 1, 8 or 24 Bitpalnes! */
  197.     long ras_length;      /* Total number of raster pixels = Width * Height */ 
  198.     long ras_type;        /* The storage type of the Bitmap */
  199.     long ras_maptype;     /* The type of the colour map used */
  200.     long ras_maplength;   /* Total length (in bytes) of the colour map */
  201.                            /* which is = 3 * (1 << #bitplanes ) */
  202.    } ;
  203.  
  204.  
  205. struct rasterfile writerast;
  206.  
  207.  
  208.                   /* An entry from the HISTOGRAM : */
  209.  
  210. typedef struct ent 
  211.         {
  212.           long  count ;           /* Colour frequency */
  213.           unsigned char map_to ;  /* Equivalent map position in the final 256 */
  214.                                   /* colour palette for the SUN */
  215.         } entry;
  216.  
  217.  
  218. entry Histogram[4096] ;   /* Histogram of ALL of the possible colours */
  219.                                  /* on the Amiga. */
  220.  
  221.  
  222. struct node               /* temporary Histogram which is sorted */
  223.       {
  224.         int colr;
  225.         long count;
  226.         unsigned char map_to;
  227.  
  228.        } sortedHist[4096];      
  229.  
  230.                     /* The SUN colour palette */
  231.  
  232. unsigned char col_RED[256],    /* RED COMPONENTS OF THE PALLETE ENTRIES */
  233.               col_GREEN[256],  /* GREEN COMPONENTS OF THE PALLETE ENTRIES */
  234.               col_BLUE[256];  /* BLUE COMPONENTS OF THE PALLETE ENTRIES */
  235.    
  236.  
  237.  
  238.  
  239. extern struct Library *OpenLibrary();   /*This should be in exec/libraries.h */
  240. extern struct Screen *OpenScreen();     /*This should be in intuition/intuition.h */
  241.  
  242. struct Library *GfxBase = NULL;
  243. struct Library *LayersBase = NULL;
  244. struct Library *IntuitionBase = NULL;
  245.  
  246.  
  247. struct Screen *PlopScreen = NULL;
  248.  
  249.  
  250. struct TextAttr PlopFont =
  251.     {
  252.         (UBYTE *)"topaz.font",  /* I think this is the ROM font */
  253.         8,
  254.         0,
  255.         0,
  256.     };
  257.  
  258.  
  259. static struct NewScreen PlopNewScreen =
  260.         {
  261.         0, 0, 0, 0, 0,
  262.         0, 1,
  263.         0,
  264.         CUSTOMSCREEN,
  265.         &PlopFont,
  266.         NULL,
  267.         NULL,
  268.         NULL,
  269.         };
  270.  
  271. struct RastPort PlopRastPort;
  272.  
  273. FILE *fd,*fopen();   /* filing devices */
  274.  
  275. unsigned short amy_cmap[MAXCOL];
  276.  
  277.  
  278.  
  279. /* Put_ea_cmap given an ea-type color map:
  280.      an array of unsigned chars of form ea_cmap[] = {r, g, b, r, g, b...}
  281.              
  282.  
  283.   turn it into an amiga-type color map:
  284.      an array of unsigned short of form amiga_cmap = {0xrgb, 0xrgb, ...}
  285.      and then tell Dale this is the colors we want for our viewport */
  286.  
  287.  
  288.  
  289.  
  290.    /* This routine will obtain the RGB colour of that x-y locn. in a HAM image */
  291.    /* NOTE: This routine assumes it is being called in order of all adjacent pixels 
  292.             in a HAM image. It is NOT a general 'readpixel' for HAM!! */
  293.         
  294. int Next_Colour(x,y)
  295. int x,y;
  296. {
  297.   static unsigned char red,
  298.                        green,
  299.                        blue;  /* previous pixel's RED GREEN & BLUE vals */
  300.  
  301.   int col_bits,          /* lower 4 bits are either the index to Amy palette */
  302.                          /* or the NEW red,green or blue component */
  303.       acol,
  304.       val,               /* current pixel's value */ 
  305.       control_bits;      /* upper 2 bits are the control bits */
  306.  
  307.   
  308.  
  309.   val = ReadPixel( &PlopScreen->RastPort,(long)x,(long)y) ;
  310.   control_bits = (val & 0x00f0) >> 4;
  311.   col_bits =  val & 0x000f;
  312.  
  313.   switch (control_bits)
  314.     {
  315.               /* normal addressing mode ... col_bits = index in Amy palette */
  316.  
  317.       case 0 :  acol = (int) amy_cmap[col_bits]; 
  318.                 red = RED(acol);                /* store away the RGB info */
  319.                 green = GREEN(acol);
  320.                 blue = BLUE(acol);
  321.                 return(acol);
  322.                 break;
  323.  
  324.  
  325.              /* col_bits represent the NEW BLUE register value of previous */
  326.              /* pixel's RGB colour. */
  327.  
  328.       case 1 :  blue = (unsigned char) (col_bits << 4);
  329.                 return(colourval(red,green,blue));
  330.                 break;
  331.  
  332.  
  333.              /* col_bits represent the NEW RED register value of previous */
  334.              /* pixel's RGB colour. */
  335.  
  336.       case 2 :  red = (unsigned char) (col_bits << 4);
  337.                 return(colourval(red,green,blue));
  338.                 break;
  339.  
  340.  
  341.              /* col_bits represent the NEW GREEN register value of previous */
  342.              /* pixel's RGB colour. */
  343.  
  344.       case 3 :  green = (unsigned char) (col_bits << 4);
  345.                 return(colourval(red,green,blue));
  346.                 break;
  347.     }
  348.  
  349. }
  350.  
  351.  
  352.               /* Write the Current Screen to a SUN raster file */
  353.  
  354. void write_rast(width,height,depth,x,y,cmap)
  355.  
  356. int width,height,depth,x,y;
  357. unsigned char *cmap;
  358. {
  359.  
  360.   int i,
  361.       acol,
  362.       actual,numcols,
  363.       maxAmigaCols,
  364.       xmax,ymax;
  365.  
  366.   long dep;
  367.  
  368.   register int xpos,ypos;
  369.  
  370.   unsigned char col;
  371.  
  372.   actual = width;
  373.   if (width & 1) actual++;
  374.  
  375.                       /* check for the single bitplane case */
  376.   if (depth != 1)
  377.     { 
  378.      numcols = 256;    /* set 8 bitplanes */
  379.      dep = 8;
  380.     }
  381.   else
  382.     {
  383.      numcols = 2 ;      /* else use 1 bitplane */
  384.      dep = 1;
  385.     }
  386.  
  387.   writerast.ras_magic = RAS_MAGIC;
  388.   writerast.ras_width = (long) width;
  389.   writerast.ras_height = (long) height;
  390.   writerast.ras_depth = (long) dep;
  391.   writerast.ras_length = (long) width * height;
  392.   writerast.ras_type = (long) RT_STANDARD;
  393.   writerast.ras_maptype = (long) RMT_EQUAL_RGB;
  394.   writerast.ras_maplength = (long) (3 * numcols);
  395.  
  396.   /* Fill the Sun colour map with RED GREEN BLUE components 
  397.      from the AMIGA'S PALLETE.
  398.   */
  399.  
  400.   if (LaceFlag)
  401.      writerast.ras_width *= 2;   /* twice the width if interlaced */
  402.  
  403.   if (depth < 6)
  404.     {
  405.       maxAmigaCols = (1 << depth);
  406.  
  407.       for (i = 0 ; i < numcols ; i++ )
  408.         {
  409.           if (i < maxAmigaCols)
  410.             {
  411.               col_RED[i] = cmap[0];        /* RED   */
  412.               col_GREEN[i] = cmap[1];      /* GREEN */ 
  413.               col_BLUE[i] = cmap[2];       /* BLUE  */
  414.               cmap += 3;
  415.             }
  416.           else
  417.             col_RED[i] = col_GREEN[i] = col_BLUE[i] = 0;
  418.  
  419. #ifdef CHECK
  420.           fprintf(stdout,"[%3u] R =%3u, G =%3u , B =%3u\n",i,
  421.                   col_RED[i],col_GREEN[i],col_BLUE[i]);  
  422. #endif CHECK   
  423.         }   
  424.     }
  425.   
  426.  
  427.  
  428.   /* Write out the header info .. */
  429.  
  430.   fwrite(&writerast,sizeof(writerast),1,fd);
  431.  
  432.   /* Write out the R,G, & B colour maps */
  433.  
  434.   fwrite(col_RED,numcols,1,fd);
  435.   fwrite(col_GREEN,numcols,1,fd);
  436.   fwrite(col_BLUE,numcols,1,fd);
  437.  
  438.   /* Begin writing out the actual bitmap ! */
  439.  
  440.   SetAPen(&PlopScreen->RastPort,1);
  441.   SetDrMd(&PlopScreen->RastPort,COMPLEMENT);
  442.  
  443.   ymax = height + y;
  444.   xmax = width + x ;
  445.  
  446.  
  447.   if (depth < 6)
  448.     {
  449.       fprintf(stdout,"Please wait, converting %d scanlines [see display] ... ",ymax);
  450.       fflush(stdout);
  451.  
  452.       for (ypos = y ; ypos < ymax ; ypos++)
  453.         {
  454.           for (xpos = x ; xpos < xmax ; xpos++ )
  455.             {
  456.               /* I hope Commodore speed up WritePixel soon or I'll kill myself !!! */
  457.  
  458.               col = ReadPixel( &PlopScreen->RastPort, (long) xpos, (long) ypos ) ;
  459.                            
  460.               WritePixel( &PlopScreen->RastPort,(long) xpos, (long) ypos ) ;
  461.  
  462.               fputc(col,fd);
  463.  
  464.               /* If the pic is interlaced then double the width */
  465.               /* have TWICE as many pixels per scanline */
  466.   
  467.               if (LaceFlag) 
  468.                 fputc(col,fd);
  469.  
  470.             } 
  471.          
  472.         } 
  473.       fprintf(stdout,"Done.\n\n"); 
  474.     }
  475.   else  /* Do the HAM case, scan the image ! */
  476.     {
  477.       fprintf(stdout,"Please wait, converting %d scanlines ... ",ymax);
  478.       fflush(stdout);
  479.  
  480.       for (ypos = y; ypos < ymax ; ypos++)
  481.         {
  482.           for (xpos = x; xpos < xmax ; xpos++ )
  483.             {
  484.              /* get the next ACTUAL colour from the screen */ 
  485.  
  486.              acol = Next_Colour(xpos,ypos);
  487.  
  488.              /* write the Sun colour palette index to the file */
  489.  
  490.              /* if the pic is interlaced then double the width */
  491.              /* have TWICE as many pixels per scanline */
  492.  
  493.              fputc(Histogram[acol].map_to,fd);
  494.  
  495.              if (LaceFlag)
  496.                fputc(Histogram[acol].map_to,fd);
  497.                              
  498.             } 
  499.         }
  500.       fprintf(stdout,"Done.\n\n");   
  501.     }                          
  502. }
  503.                                           
  504.           
  505.  
  506.  
  507. void put_ea_cmap(cmap, colors)
  508.  
  509. unsigned char *cmap;
  510. int colors;
  511.  
  512. {
  513.   int i;
  514.   unsigned char r, g, b;
  515.  
  516.   if (colors > MAXCOL)    /*color clipping*/
  517.     colors = MAXCOL;
  518.  
  519.   for (i=0; i<colors; i++)
  520.      {
  521.       amy_cmap[i] = 
  522.           ((cmap[0] & 0xf0) << 4) + (cmap[1] & 0xf0) + ((cmap[2] & 0xf0) >> 4);
  523.       cmap += 3;
  524.      } 
  525.   LoadRGB4( &PlopScreen->ViewPort, amy_cmap, (long)colors);
  526. }
  527.  
  528.  
  529.         /* back out backwards */
  530.  
  531. void plop_cleanup()
  532. {
  533.   if (PlopScreen != NULL)
  534.      CloseScreen(PlopScreen);
  535.  
  536.   if (IntuitionBase != NULL)
  537.      CloseLibrary(IntuitionBase);
  538.  
  539.   if (LayersBase != NULL)
  540.      CloseLibrary(LayersBase);
  541.  
  542.   if (GfxBase != NULL)
  543.      CloseLibrary(GfxBase);
  544. }
  545.  
  546.  
  547.  
  548.   /* This procedure will build up a histogram of all the colours */
  549.   /* used in a particular HAM image. */
  550.  
  551. void make_histogram(width,height)
  552.  
  553. int width,height;
  554.  
  555. {
  556.   int xmax,ymax,
  557.       col,
  558.       xpos,ypos;
  559.  
  560.   /* set up the drawing pen mode & colour .. */
  561.  
  562.   SetAPen(&PlopScreen->RastPort,1);
  563.   SetDrMd(&PlopScreen->RastPort,COMPLEMENT);
  564.  
  565.   /* initialize the histogram ... */
  566.  
  567.   for (col = 0; col < 4096 ; col++);
  568.      {
  569.        Histogram[col].count = 0;
  570.        Histogram[col].map_to = 0;
  571.      }
  572.  
  573.   ymax = height ;
  574.   xmax = width ;
  575.   
  576.   fprintf(stdout,"Please wait, building the histogram ... "); 
  577.   fflush(stdout);
  578.    
  579.   NumCols = 0;
  580.  
  581.   for (ypos = 0 ; ypos < ymax ; ypos++)
  582.      {
  583.        for (xpos = 0 ; xpos < xmax ; xpos++ )
  584.           {
  585.             col = Next_Colour(xpos,ypos); /* get the next RGB colour from HAM pic */
  586.  
  587.             if (Histogram[col].count == 0)  /* new colour! */
  588.                NumCols++;
  589.  
  590.             Histogram[col].count++;
  591.            
  592.           } 
  593.        
  594.      } 
  595.  
  596.   fprintf(stdout,"Done.\n");
  597. }
  598.  
  599.  
  600.  
  601.  
  602.         /* Find a colour in the SUN palette that is closest to 'colour' */
  603.         /* and return that found colour's INDEX in the SUN palette */
  604.  
  605. unsigned char best_match(colour)
  606. int colour;
  607. {
  608.   register int pos;       /* the current index */
  609.  
  610.   unsigned char fpos;      /* the found index */
  611.  
  612.   long mindist,   /* the smallest distance to a colour so far */
  613.        dist,      /* the distance (in RGB space) between 2 colours */
  614.        r,g,b,
  615.        r2,g2,b2;
  616.  
  617.   mindist = 3 * ( 256 * 256 - 1) + 100;   /* ensure we have the largest distance possible */
  618.                                           /* between any given 2 colours */
  619.  
  620.   r = RED(colour);     /* extract RED */
  621.   g = GREEN(colour);   /* extract GREEN */
  622.   b = BLUE(colour);    /* extract BLUE */
  623.  
  624.   for (pos = 0 ; pos < 256 ; pos++)
  625.      {
  626.        r2 = (long) col_RED[pos];
  627.        g2 = (long) col_GREEN[pos];
  628.        b2 = (long) col_BLUE[pos];
  629.  
  630.        dist = col_dist(r,g,b,r2,g2,b2);
  631.  
  632.        if (dist < mindist)
  633.          {
  634.           fpos = (unsigned char) pos;
  635.           mindist = dist;
  636.          }
  637.      }
  638.  
  639.   return((unsigned char) fpos);
  640. }
  641.  
  642.  
  643.  
  644.  
  645.  
  646.     /* For each colour in the Histogram find the best match in the SUN palette  */
  647.     /* and store this in the 'map_to' field of the entry */
  648.  
  649. void map_colours()
  650. {
  651.   int col;
  652.   unsigned char bestmatch();
  653.  
  654.   fprintf(stdout,"Mapping colours ... ");
  655.   fflush(stdout);
  656.  
  657.   for (col = 0 ; col < 4096 ; col++)
  658.      {
  659.       if (Histogram[col].count)
  660.           Histogram[col].map_to = (unsigned char) best_match(col);
  661.      }    
  662.   fprintf(stdout,"Done.\n\n");
  663. }
  664.  
  665.  
  666.  
  667.  
  668.         /* Comparison function use for frequency sorting the Histogram */
  669.  
  670. int cmpfreq(nod1,nod2)
  671. struct node *nod1,*nod2;
  672. {
  673.   long c1,c2;
  674.  
  675.   c1 = nod1->count;
  676.   c2 = nod2->count;
  677.  
  678.   if (c1 < c2)
  679.     return(-1);
  680.   else if (c1 > c2)
  681.     return(1);
  682.   else return(0);
  683.      
  684. }
  685.  
  686.  
  687.           /* Choose the best 256 colours out of 4096 possible colours! */
  688.  
  689.           /* This method I employ currently may seem crude, but it worked 
  690.              well in a program which went from 24 million colours to 256 !!! */ 
  691.  
  692.           /* NOTE:  ALTER THIS ROUTINE ONLY if you wish to improve the 
  693.                     colour choices! */
  694.  
  695. void make_palette()
  696. {
  697.   int col;
  698.   int register pos;
  699.  
  700.      /* store the current histogram away to a temporary histogram to be sorted */
  701.  
  702.   for (pos= 0; pos < 4096 ; pos++)
  703.      {
  704.        sortedHist[pos].colr = pos;
  705.        sortedHist[pos].count = Histogram[pos].count;
  706.        sortedHist[pos].map_to = Histogram[pos].map_to;
  707.      }
  708.  
  709.  
  710.      /* sort the histogram due to colour frequency */
  711.  
  712.   fprintf(stdout,"Sorting Histogram ... ");
  713.   fflush(stdout);
  714.  
  715.   qsort((char *)sortedHist,(unsigned) 4096,sizeof(struct node),cmpfreq);
  716.  
  717.   fprintf(stdout,"Done.\n");
  718.  
  719.  
  720. #ifdef CHECK
  721.   printf("Dumping sorted Histogram:\n");
  722.   for (pos = 0; pos < 4096 ; pos++)
  723.      if (sortedHist[pos].count)
  724.        {
  725.          col = sortedHist[pos].colr;
  726.          printf("[%4d] Colour %4d (RED %2x ,GREEN %2x, BLUE %2x) , Count %ld\n",
  727.                   pos,col,RED(col),GREEN(col),BLUE(col),sortedHist[pos].count);
  728.        }
  729. #endif
  730.  
  731.  
  732.   /* strip off the top 256 most frequent colours out of the sorted Histogram */
  733.  
  734.  
  735.   if (NumCols <= 32) 
  736.     {
  737.       fprintf(stdout,"\n\tNOTE: I suggest you convert this picture to NON-HAM and\n");
  738.       fprintf(stdout,"\t        re-run this program on it for faster conversion.\n\n");
  739.     }
  740.  
  741.   fprintf(stdout,"Choosing best 256 colours out of %d ... ",NumCols);
  742.   fflush(stdout);
  743.                         /* My old CHEAPO method : (Works though!) */
  744.  
  745.                 /* I have thrown 2 new colour choice algorithms at this
  746.                    and both didn't improve on my original method, grrrr!!!
  747.                    I am not sure if the error is in my theory or a weird bug? */
  748.                 
  749.                 /* I hope someone can come up with an improved method! */
  750.                 /* As the HAM conversions are still only 90% perfect.  */
  751.            
  752.  
  753.   for (pos = 0; pos < 256 ; pos++)
  754.     if (pos < NumCols)
  755.      {
  756.        col = sortedHist[4095-pos].colr;
  757.        col_RED[pos]   = RED(col);
  758.        col_GREEN[pos] = GREEN(col);
  759.        col_BLUE[pos]  = BLUE(col);
  760.      }
  761.     else   /* we have less than 256 colours, thus zero the rest. */
  762.      {
  763.        col_RED[pos]   = 0;
  764.        col_GREEN[pos] = 0;
  765.        col_BLUE[pos]  = 0;
  766.      }
  767.  
  768.   fprintf(stdout,"Done.\n");
  769.  
  770. }
  771.  
  772.  
  773.  
  774.  
  775.  
  776. void hist_info()
  777. {
  778.  int colcnt,    /* number of distinct colours */
  779.      maxcol;   /* it's col */
  780.  
  781.  long maxfreq,    /* maximum freq of a col */
  782.       pixcnt,     /* # pixels read in  */
  783.       cnt;        /* colour frequency */
  784.                              
  785.  
  786.  int pos;
  787.  
  788.  maxcol= maxfreq = colcnt = pixcnt = 0;
  789.  
  790.  
  791.  fprintf(stdout,"Analysing histogram ... ");
  792.  fflush(stdout);
  793.  
  794.  for(pos = 0; pos < 4096; pos++)
  795.    {
  796.      cnt = Histogram[pos].count;
  797.      if (cnt)
  798.        {
  799.          colcnt++;        /* bump the # of colours */
  800.          pixcnt += cnt;   /* keep a runing total of # pixels read so far */
  801.  
  802.          if (cnt > maxfreq) /* find MAX frequency */
  803.            {
  804.             maxfreq = cnt;
  805.             maxcol = pos;
  806.           
  807.            }
  808.  
  809.        }
  810.    } 
  811.   fprintf(stdout,"Done.\n");
  812.   fprintf(stdout,"\n\t         Histogram Information:\n");
  813.   fprintf(stdout,"\t==========================================\n");
  814.   fprintf(stdout,"\tTotal number of pixels read        =  %ld\n",pixcnt);
  815.   fprintf(stdout,"\tNumber of distinct colours         =  %d\n",colcnt); 
  816.   fprintf(stdout,"\tColour %4d has Maximum Frequency  =  %ld\n",maxcol,maxfreq);
  817.   fprintf(stdout,"\t==========================================\n\n");
  818.  
  819. }
  820.  
  821.  
  822.  
  823.  
  824. main(argc, argv)
  825. int argc;
  826. char *argv[];
  827. {
  828.   int i;
  829.   SHORT swidth,sheight,sdepth;
  830.   struct ILBM_info *info;
  831.  
  832.         /*Before we can do ANYTHING have to get our libraries... */
  833.  
  834.   if ((GfxBase =  OpenLibrary("graphics.library", (long)0)) == NULL)
  835.     {
  836.       fprintf(stderr,"Can't open Graphics Library\n");
  837.       return(-1);
  838.     }
  839.  
  840.   if ((LayersBase =  OpenLibrary("layers.library", (long)0)) == NULL)
  841.     {
  842.      fprintf(stderr,"Can't open Layers Library\n");
  843.      plop_cleanup();
  844.      return(-2);
  845.     }
  846.  
  847.         /* Two for Dale and one for RJ */
  848.  
  849.   if ((IntuitionBase =  OpenLibrary("intuition.library",(long) 0)) == NULL)
  850.     {
  851.       fprintf(stderr,"Can't open Intuition Library\n");
  852.       plop_cleanup();
  853.       return(-3);
  854.     }
  855.  
  856.  
  857.  
  858.   InitRastPort(&PlopRastPort);
  859.   PlopRastPort.Mask = 0xff;  /* enable ALL bitplanes for writing */
  860.  
  861.   if (argc < 3)
  862.     {
  863.       fprintf(stdout,"\n\t AMIGA IFF Format -> SUN RASTER BITMAP  V1.31\n\n");
  864.       fprintf(stdout,"\t   By Richard Frost.      5th March 1989.\n");
  865.       fprintf(stdout,"\t   using Jim Kent's IFF routines .. 'Jiff.c'\n\n");
  866.       fprintf(stdout,"\tConversion of HAM pics supported in this version!\n");
  867.       fprintf(stdout,"\t Aspect Ratio correction for interlace pics only.\n");
  868.       fprintf(stdout,"\n\tUSAGE: %s  <IFF-File> <SUN-Raster-File>\n\n",argv[0]);
  869.     }
  870.   else
  871.     {
  872.       fd = fopen(argv[2],"w");
  873.  
  874.       if (fd == NULL) 
  875.         {
  876.          fprintf(stderr,"Could not open file %s for read.\n",argv[1]);
  877.          exit(0);
  878.         }
  879.          
  880.       if ( (info = read_iff(argv[1], 0) ) != NULL)
  881.         {
  882.  
  883.          fprintf(stdout,"\n\tScreen Information For %s\n",argv[1]);
  884.          fprintf(stdout,"\t==============================\n");
  885.          fprintf(stdout,"\t  Display Width    =  %d\n",info->header.pageWidth);
  886.          fprintf(stdout,"\t  Display Height   =  %d\n",info->header.pageHeight);
  887.          fprintf(stdout,"\t  # Bitplanes      =  %d\n",info->header.nPlanes);
  888.          fprintf(stdout,"\t  Image X offset   =  %d\n",info->header.x);
  889.          fprintf(stdout,"\t  Image Y offset   =  %d\n",info->header.y);
  890.          fprintf(stdout,"\t  Image Width      =  %d\n",info->header.w);
  891.          fprintf(stdout,"\t  Image Height     =  %d\n",info->header.h);
  892.          fprintf(stdout,"\t==============================\n\n");
  893.  
  894.  
  895.          swidth = (SHORT) info->header.w ;
  896.          sheight = (SHORT) info->header.h ;
  897.          sdepth = (SHORT) info->header.nPlanes ;
  898.  
  899.          PlopNewScreen.Width = (SHORT) info->header.pageWidth;
  900.          PlopNewScreen.Height = (SHORT) info->header.pageHeight;
  901.          PlopNewScreen.Depth = (SHORT) info->header.nPlanes ;
  902.  
  903.  
  904.          if (sdepth == 6)   /* ie. We want HAM mode ! */
  905.              PlopNewScreen.ViewModes = HAM;
  906.  
  907.          if (info->header.pageWidth >= 640)
  908.            PlopNewScreen.ViewModes = HIRES;
  909.  
  910.          if (info->header.pageHeight >= 256)
  911.            {
  912.              PlopNewScreen.ViewModes |= INTERLACE;
  913.              if (info->header.pageWidth < 640)
  914.                {
  915.                  fprintf(stdout,"Aspect Ratio Correction ON.\n");
  916.                  LaceFlag = 1;
  917.                }
  918.              else
  919.                LaceFlag = 0;
  920.             }
  921.  
  922.          if ( (PlopScreen = OpenScreen(&PlopNewScreen) ) == NULL)
  923.            {
  924.              fprintf(stderr,"OpenScreen failed\n");
  925.              plop_cleanup();
  926.              return(-4);
  927.             }
  928.          else
  929.            {
  930.              WBenchToFront();
  931.  
  932.              if (sdepth < 6)
  933.                put_ea_cmap(&info->cmap, (1 << info->bitmap.Depth));
  934.              else
  935.                put_ea_cmap(&info->cmap,16);
  936.   
  937.               
  938.              PlopRastPort.BitMap = &info->bitmap;            
  939.              ClipBlit(&PlopRastPort, (long)0, (long)0,
  940.                      &PlopScreen->RastPort, (long)info->header.x, (long)info->header.y,
  941.                      (long)info->header.w, (long)info->header.h, (long)COPY_MINTERM);
  942.  
  943.              free_planes(&info->bitmap);
  944.  
  945.              if (sdepth == 6)    /* ie. We got a HAM pic! */
  946.                {
  947.                  make_histogram(swidth,sheight);
  948.                  hist_info();     /* OPTIONAL ROUTINE for interest only */
  949.                  make_palette();
  950.                  map_colours();
  951.                }
  952.  
  953.              write_rast(info->header.w, info->header.h,
  954.                         info->header.nPlanes,
  955.                         info->header.x, info->header.y,
  956.                         &info->cmap);
  957.              
  958.              fclose(fd);
  959.              fprintf(stdout,"\nAll Done, have a nice day.\n");
  960.            }
  961.         }
  962.  
  963.       else
  964.         fprintf(stderr,"Couldn't load %s as an IFF file\n",argv[1]);
  965.       }
  966. plop_cleanup();
  967. }
  968.  
  969.  
  970.